/*
 * @Author: linxun 
 * @Date: 2021-03-03 10:37:20 
 * @Last Modified by: linxun
 * @Last Modified time: 2021-07-27 10:45:07
 * @Description: 数据集管理
 */

import React, { useEffect, useState, Fragment } from 'react';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { Card, Button, message, Row, Col, Input, Select, Cascader, Modal, Tabs, List, Switch } from 'antd';
import { useIntl, history, connect } from 'umi';
import {
  fetchDataSet,
  delDataSet,
  fetchDataSetDetail,
  editDataSet,
  releaseDataSet,
  getTaskIdByDataSetId,
  delAnnoTask,
  cropDataSet,
  delDataSetVersions,
  segmentDataSet,
  downloadDataSet,
} from './service';
import { PAGEPARAMS, sortText, ANNOTATIONS_BACKEND } from '@/utils/const';
import TableHeader from './components/TableHeader';
import DataSetTable from './components/DataSetTable';
import SubTable from './components/SubTable';
import DatasetDetail from './components/DataSetDetail';
import EditModal from './components/EditDataSetModal';
import ProcessingModal from './components/DataProssingModal';
import RelaseModal from './components/ReleaseModal';
import SegmentModal from './components/SegmentModal';

import styles from './index.less';

const { Search } = Input;
const { Option } = Select;
const { TabPane } = Tabs;

const TAB_CONFIG = [
  { label: '原始数据集', value: '1' },
  { label: '已发布数据集', value: '2' },
];

let timer = null;
const intervalTime = 60;

const DataSetList = props => {
  const { formatMessage } = useIntl();
  const {
    dataSet: {
      labelTypes,
      labelScenes,
      labelStatus,
      listSourceType,
      createStatus,
    },
    dispatch,
    location: {
      pathname,
    },
  } = props;
  const isPublic = pathname?.includes('public');
  const [curTab, setCurTab] = useState('1');  // 1-原始数据集 2-已发布数据集
  const [loading, setLoading] = useState({
    table: false,
    detail: false,
    edit: false,
    processing: false,
    release: false,
    segment: false,
  });
  const [visible, setVisible] = useState({
    detail: false,
    edit: false,
    processing: false,
    release: false,
    segment: false,
  });
  const [tableData, setTableData] = useState({ list: [], pagination: {} });
  const [tableParams, setTableParams] = useState({ ...PAGEPARAMS, isPublished: false });
  const [searchVal, setSearchVal] = useState({});
  const [sortedInfo, setSortedInfo] = useState({ orderBy: undefined, order: undefined });
  const [versionData, setVersionData] = useState({});
  const [subTableLoading, setSubTableLoading] = useState({});
  const [versionDetail, setVersionDetail] = useState({});
  const [curRecord, setCurRecord] = useState({});

  const getDataSet = async params => {
    setLoading({ ...loading, table: true });
    const res = await fetchDataSet({
      orderBy: sortedInfo.field,
      order: sortText[sortedInfo.order],
      ...tableParams,
      ...params,
    });
    setLoading({ ...loading, table: false });
    if (res.code === 0) {
      setTableData({
        list: res.data.cvDataset.map(item => ({
          ...item,
          status: item.status || 'success', // 返回空字符串或null时默认为创建完成状态
          annotStatus: item.annotStatus || 'unlabeled', // 返回空字符串或null时默认为未标注状态
        })),
        pagination: {
          current: params?.pageNum || tableParams.pageNum,
          pageSize: params?.pageSize || tableParams.pageSize,
          total: res.data.total,
        },
      });
    }
  };

  const getSubTable = async params => {
    setSubTableLoading({
      ...subTableLoading,
      [params.datasetCode]: true,
    });
    const res = await fetchDataSet({
      ...params,
      // isLatest: false,
      isPublished: true,
    });
    setSubTableLoading({
      ...subTableLoading,
      [params.datasetCode]: false,
    });
    if (res.code === 0) {
      setVersionData({
        ...versionData,
        [params.datasetCode]: {
          list: res.data.cvDataset,
          pagination: {
            datasetCode: params.datasetCode,
            current: params?.pageNum,
            pageSize: params.pageSize,
            total: res.data.total,
          },
        }
      });
    }
  };

  const getDataSetDetail = async params => {
    setLoading({ ...loading, detail: true });
    try {
      const res = await fetchDataSetDetail(params);
      setLoading({ ...loading, detail: false });
      if (res.code === 0) {
        setVersionDetail(res.data);
      }
    } catch (err) {
      console.log(err);
    }
  };

  useEffect(() => {
    if (!labelTypes.length) {
      dispatch({ type: 'dataSet/getLabelType' });
    }
    if (!labelScenes.length) {
      dispatch({ type: 'dataSet/getLabelScenes' });
    }
    if (!labelStatus.length) {
      dispatch({ type: 'dataSet/getLabelStatus' });
    }
    if (!listSourceType.length) {
      dispatch({ type: 'dataSet/getListSourceType' });
    }
    if (!createStatus.length) {
      dispatch({ type: 'dataSet/getCreateStatus' });
    }

    if (curTab === '1') {
      timer = setInterval(getDataSet, intervalTime * 1000);
    }
    return () => {
      if (timer) {
        clearInterval(timer);
      }
    }
  }, []);

  useEffect(() => {
    getDataSet();
    if (timer) {
      clearInterval(timer);
    }
    if (curTab === '1') {
      timer = setInterval(getDataSet, intervalTime * 1000);
    }
  }, [sortedInfo, tableParams]);

  const onTabChange = key => {
    if (key !== curTab) {
      setCurTab(key);
      setTableParams({
        // ...tableParams,
        pageNum: 1,
        pageSize: 10,
        isPublished: key === '2',
        isLatest: key === '2' || undefined,
      });
      setSearchVal({});
    }
  };

  const onSorterChange = (pagination, filters, sorter) => {
    if (sorter.field) {
      const changeFields = ['createdAt', 'updatedAt'];  // 后端参数需要下划线
      const fieldMap = {
        'createdAt': 'created_at',
        'updatedAt': 'updated_at',
      };
      setSortedInfo({
        ...sorter,
        field: changeFields.includes(sorter.field) ? fieldMap[sorter.field] : sorter.order,
      });
    }
  };

  const onPageChage = (page, pageSize) => {
    setTableParams({
      ...tableParams,
      pageNum: page,
      pageSize: pageSize,
    });
  };

  const onSelectChange = (value, key) => {
    setTableParams({
      ...tableParams,
      pageNum: 1,
      [key]: value,
    });
  };

  const onSearch = (value, key) => {
    setTableParams({
      ...tableParams,
      pageNum: 1,
      [key]: value,
    });
  };

  const onSearchChange = (e, key) => {
    setSearchVal({
      ...searchVal,
      [key]: e.target.value,
    })
  };

  const onRelease = record => {
    setVisible({ ...visible, release: true });
    setCurRecord(record);
  };

  const onReleaseSubmit = async dataSetIsPublic => {
    setLoading({ ...loading, release: true });
    const res = await releaseDataSet({ cvdatasetId: curRecord.id, isPrivate: !dataSetIsPublic });
    setLoading({ ...loading, release: false });
    if (res && res.code === 0) {
      message.success('发布成功！');
      setVisible({ ...visible, release: false });
      setCurRecord({});
      onTabChange('2');
    }
  };

  const onEditClick = record => {
    setVisible({ ...visible, edit: true });
    setCurRecord(record);
  };

  const onEditSubmit = async values => {
    setLoading({ ...loading, edit: true });
    const res = await editDataSet({ id: versionDetail.id, ...values });
    setLoading({ ...loading, edit: false });
    if (res.code === 0) {
      message.success(formatMessage({ id: 'dataSet.table.option.success' }));
      setVisible({ ...visible, edit: false });
      setCurRecord({});
      getDataSet();
      if (curTab === '2') {
        getSubTable({
          datasetCode: versionDetail.datasetCode,
          ...PAGEPARAMS,
          pageSize: 5,
        });
      }
      return Promise.resolve();
    }
    return Promise.reject(res);
  };

  const onProcessing = record => {
    setVisible({ ...visible, processing: true });
    setCurRecord(record);
  };

  const onProcessingSubmit = async values => {
    setLoading({ ...loading, processing: true });
    const res = await cropDataSet({ cvDatasetId: curRecord.id, ...values });
    setLoading({ ...loading, processing: false });
    if (res.code === 0) {
      message.success(formatMessage({ id: 'dataSet.table.option.success' }));
      setVisible({ ...visible, processing: false });
      setCurRecord({});
      getDataSet();
    }
  };

  const onAnnotClick = async record => {
    const hide = message.loading('加载中...');
    try {
      const res = await getTaskIdByDataSetId({ id: record.id });
      hide();
      const hostName = `${window.location.origin}${ANNOTATIONS_BACKEND}`;
      if (res && res.code === 0) {
        const { imageTaskId } = res.data;
        window.open(`${hostName}/tasks/${imageTaskId}?annotType=${record.annotType}`);
      } else if (res && res.code === 210080003) {
        window.open(`${hostName}/tasks/create/${record.id}?annotType=${record.annotType}&withAnnotFile=${record.withAnnotFile}`);
      }
    } catch (err) {
      console.log(err);
      hide();
    }
  };

  const delDataSetHandle = async record => {
    const hide = message.loading(formatMessage({ id: 'dataSet.table.option.delete.loading' }));
    const res = await delDataSet({ id: record.id });
    hide();
    if (res.code === 0) {
      message.success(formatMessage({ id: 'dataSet.table.option.delete.success' }));
      if (tableData.pagination.current > 1 && tableData.list.length === 1) {
        setTableParams({
          ...tableParams,
          pageNum: tableParams.pageNum - 1,
        });
      } else {
        getDataSet();
      }
    }
  };

  // 删除当前数据集所有版本
  const delDataSetVersionsHandle = async record => {
    const hide = message.loading(formatMessage({ id: 'dataSet.table.option.delete.loading' }));
    const res = await delDataSetVersions({
      datasetCode: record.datasetCode,
      isPublished: 'true',
    });
    hide();
    if (res.code === 0) {
      message.success(formatMessage({ id: 'dataSet.table.option.delete.success' }));
      if (tableData.pagination.current > 1 && tableData.list.length === 1) {
        setTableParams({
          ...tableParams,
          pageNum: tableParams.pageNum - 1,
        });
      } else {
        getDataSet();
      }
    }
  };

  const onDelete = async (record, isPublish) => {
    if (isPublish) {
      // 已发布数据集不需要处理标注任务相关逻辑，并且是另外的删除接口
      delDataSetVersionsHandle(record);
    } else {
      const fetchTaskHide = message.loading('正在查询任务...');
      try {
        const fetchTaskRes = await getTaskIdByDataSetId({ id: record.id });
        fetchTaskHide();
        const { imageTaskId } = fetchTaskRes.data || {};
        if (imageTaskId) {
          // 删除标注任务
          const delTaskHide = message.loading('正在删除标注任务...');
          try {
            const delTaskRes = await delAnnoTask({ id: imageTaskId });
            delTaskHide();
            delDataSetHandle(record);
          } catch (err) {
            console.log(err);
            delTaskHide();
            message.error('删除标注任务失败，请稍后重试！');
          }
        } else {
          delDataSetHandle(record);
        }
      } catch (err) {
        console.log(err);
        fetchTaskHide();
        message.error('获取标注任务失败，请稍后重试！');
        delDataSetHandle(record);
      }
    }
  };

  const onExpand = (expanded, record) => {
    if (expanded) {
      getSubTable({
        datasetCode: record.datasetCode,
        ...PAGEPARAMS,
        pageSize: 5,
      });
    }
  };

  const onSubTableChange = pagination => {
    getSubTable({
      datasetCode: pagination.datasetCode,
      pageNum: pagination.current,
      pageSize: pagination.pageSize,
    });
  };

  const onSubTableDelete = async (record, datasetCode) => {
    const hide = message.loading(formatMessage({ id: 'dataSet.table.option.delete.loading' }));
    const res = await delDataSet({ id: record.id });
    hide();
    if (res.code === 0) {
      message.success(formatMessage({ id: 'dataSet.table.option.delete.success' }));
      const list = versionData[datasetCode]?.list;
      const pagination = versionData[datasetCode]?.pagination;
      getSubTable({
        datasetCode,
        pageNum: pagination.current > 1 && list.length === 1 ? pagination.current - 1 : pagination.current,
        pageSize: pagination.pageSize,
      });
      getDataSet();
    }
  };

  const showSubDetail = record => {
    // getDataSetDetail({ id: record.id });
    setVisible({ ...visible, detail: true });
    setVersionDetail(record);
  };

  const onSegmentClick = record => {
    setVisible({ ...visible, segment: true });
    setCurRecord(record);
  };

  const onSegmentSubmit = async values => {
    setLoading({ ...loading, segment: true });
    const res = await segmentDataSet({ cvDatasetId: curRecord.id, ...values });
    setLoading({ ...loading, segment: false });
    if (res && res.code === 0) {
      message.success('切分成功！');
      setVisible({ ...visible, segment: false });
      getDataSet({ pageNum: 1 });  // TODO? pageNum问题
      const pagination = versionData[curRecord.datasetCode]?.pagination;
      getSubTable({
        datasetCode: curRecord.datasetCode,
        pageNum: pagination.current,
        pageSize: pagination.pageSize,
      });
      setCurRecord({});
    }
  };

  const onDownLoadClick = async record => {
    const hide = message.loading('正在获取下载链接...', 0);
    const res = await downloadDataSet({ cvDatasetId: record.id });
    hide();
    if (res && res.code === 0 && res.data.downloadLink) {
      Modal.confirm({
        title: '温馨提示',
        content: '下载准备完成，请保存',
        icon: <EyeOutlined />,
        maskClosable: false,
        onOk: () => {
          window.open(res.data.downloadLink);
          return Promise.reject();
        },
        okText: '保存',
        cancelText: '关闭',
      });
    }
  };

  const onSubTableRefresh = (datasetCode) => {
    const pagination = versionData[datasetCode]?.pagination;
    getSubTable({
      datasetCode,
      pageNum: pagination.current,
      pageSize: pagination.pageSize,
    });
  };

  const expandedRowRender = record => {
    const data = versionData[record.datasetCode] || { list: [], pagination: {} };
    const loading = subTableLoading[record.datasetCode];
    return (
      <SubTable
        data={data}
        loading={loading}
        onSubTableChange={onSubTableChange}
        onDelete={onSubTableDelete}
        onDetailClick={showSubDetail}
        isPublic={isPublic}
        listSourceType={listSourceType}
        onSegmentClick={onSegmentClick}
        createStatus={createStatus}
        onDownLoadClick={onDownLoadClick}
        onRefresh={onSubTableRefresh}
      />
    );
  };

  return (
    <PageHeaderWrapper>
      <Card>
        <Tabs
          type='card'
          onChange={onTabChange}
          activeKey={curTab}
          animated={{ inkBar: true, tabPane: true }}
          size='large'
        >
          {TAB_CONFIG.map(item => (
            <TabPane tab={item.label} key={item.value}>
              <TableHeader
                onSelectChange={onSelectChange}
                labelTypes={labelTypes}
                labelStatus={labelStatus}
                onSearch={onSearch}
                onSearchChange={onSearchChange}
                searchVal={searchVal}
                curTab={curTab}
                onRefresh={() => getDataSet()}
                isPublic={isPublic}
                searchValue={tableParams}
              />
              <DataSetTable
                tableData={tableData}
                onDelete={onDelete}
                onPageChage={onPageChage}
                onSorterChange={onSorterChange}
                expandedRowRender={expandedRowRender}
                onExpand={onExpand}
                loading={loading.table}
                onRelease={onRelease}
                onEditClick={onEditClick}
                onDetailClick={showSubDetail}
                curTab={curTab}
                onProcessing={onProcessing}
                onAnnotClick={onAnnotClick}
                isPublic={isPublic}
                labelTypes={labelTypes}
                labelScenes={labelScenes}
                labelStatus={labelStatus}
                listSourceType={listSourceType}
                createStatus={createStatus}
              />
            </TabPane>
          ))}
        </Tabs>
        <DatasetDetail
          title={formatMessage({ id: 'menu.dataManage.dataSetDetail' })}
          detail={versionDetail}
          loading={loading.detail}
          cancel={() => setVisible({ ...visible, detail: false })}
          visible={visible.detail}
          hideVersion={curTab === '1'}
          labelTypes={labelTypes}
          labelScenes={labelScenes}
          listSourceType={listSourceType}
          canEdit={true}
          onEditSubmit={onEditSubmit}
        />
        <EditModal
          visible={visible.edit}
          loading={loading.edit}
          cancel={() => setVisible({ ...visible, edit: false })}
          onSubmit={onEditSubmit}
          curRecord={curRecord}
        />
        <ProcessingModal
          visible={visible.processing}
          loading={loading.processing}
          cancel={() => setVisible({ ...visible, processing: false })}
          onSubmit={onProcessingSubmit}
          curRecord={curRecord}
          labelScenes={labelScenes}
          labelTypes={labelTypes}
        />
        <RelaseModal
          visible={visible.release}
          loading={loading.release}
          cancel={() => setVisible({ ...visible, release: false })}
          onSubmit={onReleaseSubmit}
        />
        <SegmentModal
          visible={visible.segment}
          loading={loading.segment}
          cancel={() => setVisible({ ...visible, segment: false })}
          onSubmit={onSegmentSubmit}
          curRecord={curRecord}
        />
      </Card>
    </PageHeaderWrapper>
  )
};

export default connect(({ oldDataSet }) => ({
  dataSet: oldDataSet,
}))(DataSetList);